package data

import (
	"bytes"
	"fmt"
	"gitchina/kly_service/util"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql"
	"strconv"
	"time"
)

type CarrierPubDto struct {
	Id           int     `orm:"pk;auto;column(id)"`
	MemberId     int     `orm:"column(member_id)"`
	SrcProvince  int     `orm:"column(src_province)"`
	SrcCity      int     `orm:"column(src_city)"`
	SrcCounty    int     `orm:"column(src_county)"`
	DestProvince int     `orm:"column(dest_province)"`
	DestCity     int     `orm:"column(dest_city)"`
	DestCounty   int     `orm:"column(dest_county)"`
	Price        float32 `orm:"column(price)"`
	ShipmentTime string  `orm:"column(shipment_time)"`
	State        int     `orm:"column(state)"`
	VehicleType  int     `orm:"column(vehicle_type)"`
	VehicleLen   int     `orm:"column(vehicle_len)"`
	VehicleLoad  int     `orm:"column(vehicle_load)"`
}

type QueryCarrierPubListParam struct {
	StartArea   int
	EndArea     int
	TimeBegin   string
	TimeEnd     string
	VehicleType string
	VehicleLen  string
	VehicleLoad string
	PageNo      int
	PageSize    int
}

type CarrierPubDetail struct {
	Name           string  `orm:"column(name)"`
	OwnerPhone     string  `orm:"column(phone)"`
	OwnerStars     int     `orm:"column(stars)"`
	CarrierPubId   int     `orm:"column(pub_id)"`
	MemberId       int     `orm:"column(member_id)"`
	SrcProvince    int     `orm:"column(src_province)"`
	SrcCity        int     `orm:"column(src_city)"`
	SrcCounty      int     `orm:"column(src_county)"`
	DestProvince   int     `orm:"column(dest_province)"`
	DestCity       int     `orm:"column(dest_city)"`
	DestCounty     int     `orm:"column(dest_county)"`
	Price          float32 `orm:"column(price)"`
	ShipmentTime   string  `orm:"column(shipment_time)"`
	VehicleType    string  `orm:"column(vehicle_type)"`
	VehicleLen     string  `orm:"column(vehicle_len)"`
	VehicleLoad    string  `orm:"column(vehicle_load)"`
	VehicleNo      string  `orm:"column(vehicle_No)"`
	MemberPhotoUrl string  `orm:"column(photo)"`
}

type CarrierPubListDto struct {
	OwnerName       string  `orm:"column(name)"`
	OwnerPhone      string  `orm:"column(phone)"`
	OwnerStars      int     `orm:"column(stars)"`
	OwnerId         int     `orm:"column(member_id)"`
	CarrierPubId    int     `orm:"column(pub_id)"`
	SrcProvince     int     `orm:"column(src_province)"`
	SrcCity         int     `orm:"column(src_city)"`
	SrcCounty       int     `orm:"column(src_county)"`
	DestProvince    int     `orm:"column(dest_province)"`
	DestCity        int     `orm:"column(dest_city)"`
	DestCounty      int     `orm:"column(dest_county)"`
	Price           float32 `orm:"column(price)"`
	ShipmentTime    string  `orm:"column(shipment_time)"`
	VehicleType     string  `orm:"column(vehicle_type)"`
	VehicleLen      string  `orm:"column(vehicle_len)"`
	VehicleLoad     string  `orm:"column(vehicle_load)"`
	VehiclePhotoUrl string  `orm:"column(vehicle_photo)"`
}

func init() {
	orm.RegisterModel(new(CarrierPubDto))
}

func (c *CarrierPubDto) TableName() string {
	return "l_carrier_pub"
}

func (l LogisticsRepo) AddCarrierPub(dto *CarrierPubDto) (id int64, err error) {
	var id_tmp int
	var num int64
	var list orm.ParamsList
	o := orm.NewOrm()
	num, err = o.Raw(SQL_Logis_Last_Carrier_Pub, dto.MemberId).ValuesFlat(&list)
	if err == nil {
		if num == 0 {
			num, err = o.Raw(SQL_Mbr_Get_Vehicle_Info, dto.MemberId).ValuesFlat(&list)
			if num > 0 {
				dto.VehicleType, err = strconv.Atoi(list[0].(string))
				dto.VehicleLen, err = strconv.Atoi(list[2].(string))
				id, err = o.Insert(dto)
			}
		} else {
			id_tmp, err = strconv.Atoi(list[0].(string))
			if err != nil {
				err = fmt.Errorf("unexpected id:%s", list[0].(string))
			} else {
				id = int64(id_tmp)
				state := list[1].(string)
				if state == "0" {
					o.Raw(SQL_Logis_Upd_Carrier_Pub, dto.SrcProvince, dto.SrcCity, dto.SrcCounty,
						dto.DestProvince, dto.DestCity, dto.DestCounty, dto.Price, dto.ShipmentTime, id, state).Exec()
				} else if state == "2" || state == "3" {
					num, err = o.Raw(SQL_Mbr_Get_Vehicle_Info, dto.MemberId).ValuesFlat(&list)
					if num > 0 {
						dto.VehicleType, err = strconv.Atoi(list[0].(string))
						dto.VehicleLen, err = strconv.Atoi(list[2].(string))
						id, err = o.Insert(dto)
					}
				} else {
					err = fmt.Errorf("invalid state to update or insert. state:%s", state)
				}
			}
		}
	}

	return
}

func (l LogisticsRepo) CancelCarrierPub(memberId, carrierPubId int) (err error) {
	o := orm.NewOrm()
	_, err = o.Raw(SQL_Logis_Cancel_Carrier_Pub, carrierPubId, memberId).Exec()
	return
}

func (l LogisticsRepo) GetCarrierPub(memberId int) (CarrierPubDto, error) {
	var pub CarrierPubDto
	o := orm.NewOrm()
	err := o.Raw(SQL_Logis_Get_Carrier_Pub, memberId).QueryRow(&pub)
	return pub, err
}

func (l LogisticsRepo) QueryCarrierPubList(param QueryCarrierPubListParam) ([]CarrierPubListDto, int, error) {
	var num int64
	var rowCount int
	var err error
	var list []CarrierPubListDto
	var flat orm.ParamsList
	o := orm.NewOrm()
	format, args := l.getQueryCarrierPubListCond(param, false)
	countFormat, countArgs := l.getQueryCarrierPubListCond(param, true)
	if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Carrier_Pub_List, format), args).QueryRows(&list); num >= 1 {
		if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Carrier_Pub_List_Count, countFormat), countArgs).ValuesFlat(&flat); num >= 1 {
			rowCount, err = strconv.Atoi(flat[0].(string))
			util.GetLogger().Debug("[data-QueryCarrierPubList] - debug:rowcount::%s", flat[0])
		}
	}
	return list, rowCount, err
}

func (l LogisticsRepo) GetCarrierPubDetail(pubId int) (CarrierPubDetail, error) {
	var detail CarrierPubDetail
	o := orm.NewOrm()
	err := o.Raw(SQL_Logis_Get_Carrier_Pub_Detail, pubId).QueryRow(&detail)
	return detail, err
}

func (r LogisticsRepo) getQueryCarrierPubListCond(param QueryCarrierPubListParam, ignoreLimit bool) (string, []interface{}) {
	var buffer bytes.Buffer
	var args = make([]interface{}, 0)
	if param.StartArea != 0 {
		if param.StartArea%10000 == 0 {
			buffer.WriteString(" AND src_province = ?")
		} else if param.StartArea%100 == 0 {
			buffer.WriteString(" AND src_city = ?")
		} else {
			buffer.WriteString(" AND src_county = ?")
		}
		args = append(args, param.StartArea)
	}
	if param.EndArea != 0 {
		if param.EndArea%10000 == 0 {
			buffer.WriteString(" AND dest_province = ?")
		} else if param.EndArea%100 == 0 {
			buffer.WriteString(" AND dest_city = ?")
		} else {
			buffer.WriteString(" AND dest_county = ?")
		}
		args = append(args, param.EndArea)
	}

	if param.VehicleLen != "" {
		buffer.WriteString(" AND p.vehicle_len = ?")
		args = append(args, param.VehicleLen)
	}

	if param.VehicleLoad != "" {
		buffer.WriteString(" AND p.vehicle_load = ?")
		args = append(args, param.VehicleLoad)
	}

	if param.VehicleType != "" {
		buffer.WriteString(" AND p.vehicle_type = ?")
		args = append(args, param.VehicleType)
	}

	var time_begin string
	var time_end string
	if param.TimeBegin == "" {
		time_begin = time.Now().Format("2006-01-02 15:04:05")
	}
	if param.TimeEnd == "" {
		time_end = time.Now().AddDate(0, 1, 1).Format("2006-01-02 00:00:00")
	}

	buffer.WriteString(" AND shipment_time >= ?")
	buffer.WriteString(" AND shipment_time <= ?")
	if !ignoreLimit {
		buffer.WriteString(fmt.Sprintf(" ORDER BY p.id DESC LIMIT %d, %d", (param.PageNo-1)*param.PageSize, param.PageSize))
	}
	args = append(args, time_begin, time_end)

	return buffer.String(), args
}
